package com.xiaode.controller.admin.login;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.SecureUtil;
import cn.hutool.json.JSONUtil;

import com.jfinal.kit.Kv;
import com.jfinal.kit.Ret;
import com.jfinal.plugin.activerecord.Db;
import com.jfinal.plugin.activerecord.Record;
import com.jfinal.plugin.redis.Redis;
import com.xiaode.common.UserTokenManager;
import com.xiaode.common.constant.Const;
import com.xiaode.common.model.*;
import com.xiaode.exce.EnumError;
import com.xiaode.util.SnowflakeIdWorker;
import com.xiaode.util.welink.WeLinkUtil;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.util.*;
import java.util.stream.Collectors;

public class LoginService {
	
	/**
	 * 用户登陆
	 */
	public Ret login(String account, String password, String code, Integer platform) throws Exception {

		UserAccount ua = null;
		if (platform == 2) {// 基座
			// 判断是否绑定
			if (StrUtil.isBlank(code)) {
				return Ret.fail().set("error", EnumError.NOT_HAVE_BASE_PARAM.getObj());
			}
			String wlUserId = WeLinkUtil.getWLUserId(code);//
			if (StrUtil.isBlank(wlUserId)) {
				return Ret.fail().set("error", EnumError.BASE_LOGIN_FAIL.getObj());
			}
			ua = UserAccount.dao.findFirst("SELECT * FROM user_account WHERE eduID = ?", wlUserId);
			if (BeanUtil.isEmpty(ua)) {// 未绑定
				// 生成一个code
				String binDingCode = SnowflakeIdWorker.generateId().toString();
				Redis.use().setex(Const.binDingCode + binDingCode, Const.binDingCodeLiveSeconds, wlUserId);
				return Ret.ok("binDingCode", binDingCode);
			}
		} else if (platform == 1 || platform == 3) {// 需要账号密码
			if (StrUtil.isBlank(account) || StrUtil.isBlank(password)) {
				return Ret.fail().set("error", EnumError.ACCOUNT_PASSWORD_ERROR.getObj());
			}
			ua = UserAccount.dao.findFirst("SELECT * FROM user_account WHERE account = ? AND is_dele = 0 AND state = 1",account);
			if (BeanUtil.isEmpty(ua)) {
				return Ret.fail().set("error", EnumError.ACCOUNT_ERROR.getObj());
			}
			if (!StrUtil.equals(SecureUtil.md5(password + ua.getId() + Const.salt), ua.getPassword())) {
				return Ret.fail().set("error", EnumError.PASSWORD_ERROR.getObj());
			}
		} else {
			return Ret.fail().set("error", EnumError.PLATFORM_ERROR.getObj());
		}

		Integer userType = ua.getUserType();
		if (userType != Const.UserType.admin) {
			return Ret.fail().set("error", EnumError.AUTHORITY_NOT_EXIT.getObj());
		}
		// 老师
		Admin t = Admin.dao.findFirst("SELECT * FROM admin WHERE accountId = ?", ua.getId());
//			Redis.use().setex(Const.user.loginAdmin + ua.getId(), Const.user.timeToLiveSeconds, t);// 存用户
		Redis.use().zadd(Const.user.lastLoginTimeT,LocalDateTime.now().toInstant(ZoneOffset.of("+8")).toEpochMilli(), t.getId());// 存最后登陆时间

		// 权限
		List<OrgClass> all = OrgClass.dao.find("SELECT * FROM org_class WHERE adminGradeId < 4");
		Map<Integer, Integer> map = all.stream().collect(Collectors.toMap(OrgClass::getId, OrgClass::getAdminGradeId));
		
		String roleIds = t.getRoleIds();
        List<Integer> roleIdList = JSONUtil.toList(roleIds, Integer.class);
        List<Role> roles = Role.dao.find("SELECT id FROM role WHERE state = 2");
        Set<Integer> hashSet = roles.stream().map(role -> role.getId()).collect(Collectors.toSet());
        List<Integer> role = roleIdList.stream().filter(integer -> !hashSet.contains(integer)).collect(Collectors.toList());
	    List<Record> authoritys = Db.template("findAuthoritys", Kv.by("roleId", role)).find();
        Set<String> permissions = authoritys.stream().map(record -> record.getStr("permission")).collect(Collectors.toSet());
		ArrayList<String> strings = new ArrayList<String>(permissions);
        if (strings == null || strings.size() == 0) {
            return Ret.fail().set("error", EnumError.AUTHORITY_NULL.getObj());
        }
        t.put("authoritys", strings);
		

		// 查询架构管理
		Set<Integer> frameworkPermission = frameworkPermission(t);
		t.put("permission", frameworkPermission);
		t.put("frameworkPermission", frameworkPermission);
		List<Integer> clasList = OrgAdmin.dao.find("SELECT * FROM org_admin WHERE adminId = ? AND stratum = 3", t.getId()).stream().map(OrgAdmin::getStratumId).collect(Collectors.toList());
		t.put("clasIdList", clasList);
		int stratum = 0;
		List<OrgAdmin> oas = OrgAdmin.dao.find("SELECT * FROM org_admin WHERE adminId = ?", t.getId());
		HashSet<Integer> gradeIds = new HashSet<>();
		for (OrgAdmin oa : oas) {
			if (stratum == 0) {
				if (oa.getStratum() > stratum) {
					stratum = oa.getStratum();
				}
			} else {
				if (oa.getStratum() < stratum) {
					stratum = oa.getStratum();
				}
			}
			if (oa.getStratum() == 1) {
				gradeIds.add(1);
				gradeIds.add(2);
				gradeIds.add(3);
			} else if (oa.getStratum() == 2) {
				if (oa.getStratumId() < 4) {
					gradeIds.add(oa.getStratumId());
					t.put("runGradeId", oa.getStratumId());
				}
			} else {
				Integer integer = map.get(oa.getStratumId());
				if (integer != null) {
					gradeIds.add(integer);
				}
			}
		}
		t.put("gradeId", gradeIds);
		t.put("stratum", stratum);

		String userToken = UserTokenManager.generateToken(Kv.by("accountId", ua.getId()).set("userId", t.getId()).set("userType", Const.UserType.admin).set("canLoginAdmin",ua.getCanLoginAdmin()).set("account", ua.getAccount()).toJson());
		Redis.use().setex(Const.user.loginAdmin + ua.getId(), Const.user.timeToLiveSeconds, t);
		Redis.use().setex("userToken:"+userToken, Const.user.timeToLiveSeconds, ua.getId());
		
		return Ret.ok("user", t).set("token", userToken).set("usertype", Const.UserType.admin);
		
	}
	
	
	/**
	 * app用户和基座用户绑定 绑定成功后直接登录
	 */
	public Ret binDing(String account, String password, String banDingCode) throws Exception {
		UserAccount userAccount = UserAccount.dao.findFirst("SELECT * FROM user_account WHERE account = ? AND is_dele = 0 AND state = 1", account);
		if (BeanUtil.isEmpty(userAccount)) {
			return Ret.fail().set("error", EnumError.ACCOUNT_NO.getObj());
		}
		if (!StrUtil.equals(SecureUtil.md5(password + userAccount.getId() + Const.salt), userAccount.getPassword())) {
			return Ret.fail().set("error", EnumError.PASSWORD_ERROR.getObj());
		}
		// 是否已经绑定
		if (userAccount.getIsBindingPedestal()) {// 已经绑定
			return Ret.fail().set("error", EnumError.WELINK_HAVE_BINDING.getObj());
		}
		Integer userType = userAccount.getUserType();
		if (userType != Const.UserType.admin) {
			return Ret.fail().set("error", EnumError.AUTHORITY_NOT_EXIT.getObj());
		}
		String wlUserId = Redis.use().get(Const.binDingCode + banDingCode);
		userAccount.setIsBindingPedestal(true);
		userAccount.setEduID(wlUserId);
		userAccount.update();
		
		Admin t = Admin.dao.findFirst("SELECT * FROM admin WHERE accountId = ?", userAccount.getId());
		Redis.use().zadd(Const.user.lastLoginTimeT,LocalDateTime.now().toInstant(ZoneOffset.of("+8")).toEpochMilli(), t.getId());// 存最后登陆时间

		// 权限
		List<OrgClass> all = OrgClass.dao.find("SELECT * FROM org_class WHERE adminGradeId < 4");
		Map<Integer, Integer> map = all.stream().collect(Collectors.toMap(OrgClass::getId, OrgClass::getAdminGradeId));
		// 查询架构管理
		Set<Integer> frameworkPermission = frameworkPermission(t);
		t.put("permission", frameworkPermission);
		List<Integer> clasList = OrgAdmin.dao.find("SELECT * FROM org_admin WHERE adminId = ? AND stratum = 3", t.getId()).stream().map(OrgAdmin::getStratumId).collect(Collectors.toList());
		t.put("clasIdList", clasList);
		int stratum = 0;
		List<OrgAdmin> oas = OrgAdmin.dao.find("SELECT * FROM org_admin WHERE adminId = ?", t.getId());
		HashSet<Integer> hashSet = new HashSet<>();
		for (OrgAdmin oa : oas) {
			if (stratum == 0) {
				if (oa.getStratum() > stratum) {
					stratum = oa.getStratum();
				}
			} else {
				if (oa.getStratum() < stratum) {
					stratum = oa.getStratum();
				}
			}
			if (oa.getStratum() == 1) {
				hashSet.add(1);
				hashSet.add(2);
				hashSet.add(3);
			} else if (oa.getStratum() == 2) {
				if (oa.getStratumId() < 4) {
					hashSet.add(oa.getStratumId());
					t.put("runGradeId", oa.getStratumId());
				}
			} else {
				Integer integer = map.get(oa.getStratumId());
				if (integer != null) {
					hashSet.add(integer);
				}
			}
		}
		t.put("gradeId", hashSet);
		t.put("stratum", stratum);

		String userToken = UserTokenManager.generateToken(Kv.by("accountId", userAccount.getId()).set("userId", t.getId()).set("userType", Const.UserType.admin).set("canLoginAdmin",userAccount.getCanLoginAdmin()).set("account", userAccount.getAccount()).toJson());
		Redis.use().setex(Const.user.loginAdmin + t.getId(), Const.user.timeToLiveSeconds, t);
		Redis.use().setex("userToken:"+userToken, Const.user.timeToLiveSeconds, t.getId());
		return Ret.ok("user", t).set("token", userToken).set("usertype", Const.UserType.admin);
		
	}
	

    public Ret outLogin(Admin admin) {
        Redis.use().del(Const.user.loginAdmin + admin.getAccountId());
        return Ret.ok();
    }

    public Ret getMeInfo(Admin admin) throws Exception {
        // 角色拥有的权限
        if (BeanUtil.isEmpty(admin)) {
            return Ret.fail().set("error", EnumError.USER_NOT_LOGIN.getObj());
        }
        //查询架构权限
//        Set<Integer> integers = frameworkPermission(admin);
//        admin.put("permission", integers);


        return Ret.ok("admin", admin).set("gradeClassInfo", findGradeClassInfo()).set("roleList", roleOptions());
    }


    public static List<OrgGrade> findGradeClassInfo() {
        //查询学生届别班级
        List<OrgGrade> orgGrades = OrgGrade.dao.find("SELECT id,name FROM org_grade WHERE isRoot = 0");
        for (OrgGrade orgGrade : orgGrades) {
            List<OrgClass> orgClasses = OrgClass.dao.find("SELECT id,name FROM org_class WHERE adminGradeId = ?", orgGrade.getId());
            orgGrade.put("class", orgClasses);
        }
        return orgGrades;
    }

    public static List<Kv> roleOptions() {
        List<Role> roleList = Role.dao.findAll();
        List<Kv> list = new LinkedList<>();
        roleList.forEach(item -> {
            Kv kv = Kv.create();
            kv.set("value", item.getId());
            kv.set("label", item.getName());
            list.add(kv);
        });
        return list;
    }


    public static Set<Integer> frameworkPermission(Admin admin) {
        List<OrgAdmin> orgAdmins = OrgAdmin.dao.find("SELECT stratum,adminId,stratumId FROM org_admin WHERE adminId = ?", admin.getId());
        HashSet<Integer> hashSet = new HashSet<>();
        for (OrgAdmin orgAdmin : orgAdmins) {
            Integer stratum = orgAdmin.getStratum();
            if (stratum == 1) {
                List<OrgClass> orgClass = OrgClass.dao.find("SELECT id FROM org_class");
                Set<Integer> collect = orgClass.stream().map(orgClass1 -> orgClass1.getId()).collect(Collectors.toSet());
                hashSet.addAll(collect);
                break;
            } else if (stratum == 2) {
                List<OrgClass> orgClasses = OrgClass.dao.find("SELECT id FROM org_class WHERE adminGradeId = ?", orgAdmin.getStratumId());
                Set<Integer> collect = orgClasses.stream().map(orgClass -> orgClass.getId()).collect(Collectors.toSet());
                hashSet.addAll(collect);
            } else {
                OrgClass orgClass = OrgClass.dao.findById(orgAdmin.getStratumId());
                if (orgClass != null) {
                    hashSet.add(orgClass.getId());
                }
            }
        }
        return hashSet;
    }

}
